
package projetocompiladores;

import analisadorlexico.ProcessadorLexico;
import analisadorsintatico.CommandsGraph;
import analisadorsintatico.GraphNode;
import analisadorsintatico.GraphNode.Tipo;
import analisadorsintatico.ProcessadorSintatico;
import java.awt.Color;
import java.awt.Component;
import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jhotdraw.draw.AttributeKeys;
import org.jhotdraw.draw.DefaultDrawing;
import org.jhotdraw.draw.DefaultDrawingView;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.EllipseFigure;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.geom.Geom;

/**
 *
 * @author Anderson
 */
public class CommandsGraphFigure {

    private CommandsGraph commands;
    private Drawing screen;
    private GraphNode root;
    private Point2D.Double startPosition;

    private ArrayList<Figure> commandFigures;
    private ArrayList<LabeledBezierConnectionFigure> connectionFigures;

    private static final int componentSizeX = 100;
    private static final int componentSizeY = 80;

    public CommandsGraphFigure() {
        
    }

    public void runAnalisadores() throws FileNotFoundException, IOException {
        ProcessadorLexico lexico = new ProcessadorLexico();

        String program = "";
        int caracter;
//        BufferedReader reader = new BufferedReader(new FileReader("teste.txt"));
//        BufferedReader reader = new BufferedReader(new FileReader("teste2.txt"));
//        BufferedReader reader = new BufferedReader(new FileReader("teste3.txt"));
        BufferedReader reader = new BufferedReader(new FileReader("teste3.txt"));
        while((caracter = reader.read()) != -1) {
            program += (char) caracter;
        }

        lexico.run(program);

        ProcessadorSintatico sintatico = new ProcessadorSintatico(lexico.getTabela());
        sintatico.run();

        commands = sintatico.getCommandsGraph();
        root = commands.getRoot();
        commands.display();
    }

    public void graphToFigures(FigureGraph figureGraph) {
        ArrayList<GraphFigureNode> graph = figureGraph.getArray();
        commandFigures = new ArrayList<Figure>(graph.size());

        Figure figure;
        Point2D.Double position = new Point2D.Double();
        for(GraphFigureNode node : graph) {
            if(node.getTipo() == Tipo.START || node.getTipo() == Tipo.END) {
                position.x = startPosition.x + (node.getPosition().x * componentSizeX);
                position.y = startPosition.y + (node.getPosition().y * componentSizeY);
                figure = StatementFigureUtils.createNormalStatementFigure(node.getCommand(), position);
                position.x = startPosition.x - figure.getBounds().width/2;
                System.out.println("comando = " + node.getCommand() + " / posicao = " + position);
                figure = StatementFigureUtils.createNormalStatementFigure(node.getCommand(), position);
                figure.set(AttributeKeys.FILL_COLOR, new Color(255, 0, 0));
                commandFigures.add(figure);
                
            } else if(node.getTipo() == Tipo.NORMAL) {
                position.x = startPosition.x + (node.getPosition().x * componentSizeX);
                position.y = startPosition.y + (node.getPosition().y * componentSizeY);
                figure = StatementFigureUtils.createNormalStatementFigure(node.getCommand(), position);
                position.x = position.x - figure.getBounds().width/2;
                System.out.println("comando = " + node.getCommand() + " / posicao = " + position);
                figure = StatementFigureUtils.createNormalStatementFigure(node.getCommand(), position);
                figure.set(AttributeKeys.FILL_COLOR, new Color(255, 255, 0));
                commandFigures.add(figure);

            } else if(node.getTipo() == Tipo.IF) {
//                System.out.println("node position = " + node.getPosition());
                position.x = startPosition.x + (node.getPosition().x * componentSizeX);
                position.y = startPosition.y + (node.getPosition().y * componentSizeY);
//                System.out.println("if position = " + position);
                figure = StatementFigureUtils.createIfStatementFigure(node.getCommand(), position);
                position.x = position.x - figure.getBounds().width/2;
                System.out.println("comando = " + node.getCommand() + " / posicao = " + position);
                figure = StatementFigureUtils.createIfStatementFigure(node.getCommand(), position);
                figure.set(AttributeKeys.FILL_COLOR, new Color(0, 255, 255));
                commandFigures.add(figure);

            } else if(node.getTipo() == Tipo.TRUE) {
//                System.out.println("opaaaaaaaa");
                continue;
            } else if(node.getTipo() == Tipo.FALSE) {
                continue;
            } else if(node.getTipo() == Tipo.WHILE) {

            } else if(node.getTipo() == Tipo.DO) {
                continue;
            }
        }
    }

    public void drawConnections(FigureGraph figureGraph) {
        ArrayList<GraphFigureNode> graph = figureGraph.getArray();
        connectionFigures = new ArrayList<LabeledBezierConnectionFigure>();

        LabeledBezierConnectionFigure figure = null;
        LabeledBezierConnectionFigure figure2;
        for(int index = 0; index < graph.size(); index++) {
            GraphFigureNode node = graph.get(index);
//        for(GraphFigureNode node : graph) {
            if(node.getTipo() == Tipo.NORMAL || node.getTipo() == Tipo.START) {
//                System.out.println("node = " + node.getCommand());
                if(node.getLinkTo().get(0).x == graph.get(index+1).getPosition().x) {
                    Figure f1 = screen.findFigure(
                            new Point2D.Double(startPosition.x + node.getPosition().x * componentSizeX + 20,
                                               startPosition.y + node.getPosition().y * componentSizeY + 20));
                    Figure f2;
                    for(Point2D.Double figurePosition : node.getLinkTo()) {
                         f2 = screen.findFigure(
                               new Point2D.Double(startPosition.x + figurePosition.x * componentSizeX + 20,
                                                  startPosition.y + figurePosition.y * componentSizeY + 20));
                         if(f2 != null) {
                             figure = new LabeledBezierConnectionFigure();
                             figure.setStartConnectorPosition(Geom.south(f1.getBounds()));
                             figure.setEndConnectorPosition(Geom.north(f2.getBounds()));
                             try {
                                 figure.draw();
                             } catch (Exception ex) {
                                 Logger.getLogger(CommandsGraphFigure.class.getName()).log(Level.SEVERE, null, ex);
                             }
                         }
                    }
                } else {
                     Figure f1 = screen.findFigure(
                            new Point2D.Double(startPosition.x + node.getPosition().x * componentSizeX + 20,
                                               startPosition.y + node.getPosition().y * componentSizeY + 20));
                     Figure f2;
                     Point2D.Double figurePosition = graph.get(index+1).getPosition();
                     f2 = screen.findFigure(
                           new Point2D.Double(startPosition.x + figurePosition.x * componentSizeX + 20,
                                              startPosition.y + figurePosition.y * componentSizeY + 20));
                     if(f2 != null) {
                         EllipseFigure junction = new EllipseFigure(f2.getBounds().getCenterX() - 5,
                                                                    (f1.getBounds().getMaxY() + f2.getBounds().getMinY()) / 2 - 10,
                                                                    10, 10);
                         junction.set(AttributeKeys.FILL_COLOR, Color.DARK_GRAY);
                         screen.add(junction);

                         figure2 = new LabeledBezierConnectionFigure();
                         figure2.setStartConnectorPosition(Geom.south(junction.getBounds()));
                         figure2.setEndConnectorPosition(Geom.north(f2.getBounds()));
                         try {
                             figure2.draw();
                         } catch (Exception ex) {
                             Logger.getLogger(CommandsGraphFigure.class.getName()).log(Level.SEVERE, null, ex);
                         }
                         connectionFigures.add(figure2);

                         figure = new LabeledBezierConnectionFigure();
                         figure.setStartConnectorPosition(Geom.south(f1.getBounds()));
                         figure.addNode(new Point2D.Double(f1.getBounds().getCenterX(),
                                                           junction.getBounds().getCenterY()));
                         figure.setEndConnectorPosition(Geom.west(junction.getBounds()));
                         try {
                             figure.draw();
                         } catch (Exception ex) {
                             Logger.getLogger(CommandsGraphFigure.class.getName()).log(Level.SEVERE, null, ex);
                         }
                     }
                }
                connectionFigures.add(figure);
            } else if(node.getTipo() == Tipo.IF) {
//                System.out.println("tipo do node = IF / posicao = " + node.getPosition());
//                System.out.println("procurando em = " + new Point2D.Double(startPosition.x + node.getPosition().x * componentSizeX,
//                                           startPosition.y + node.getPosition().y * componentSizeY));
                Figure f1 = screen.findFigure(
                        new Point2D.Double(startPosition.x + node.getPosition().x * componentSizeX + 20,
                                           startPosition.y + node.getPosition().y * componentSizeY + 20));
//                System.out.println("figure = " + f1);
//                System.out.println("texto = " + ((LabeledDiamondFigure)f1).getText());
                Figure f2;
                for(Point2D.Double figurePosition : node.getLinkTo()) {
                    System.out.println("link = " + figurePosition);
                     f2 = screen.findFigure(
                           new Point2D.Double(startPosition.x + figurePosition.x * componentSizeX + 20,
                                              startPosition.y + figurePosition.y * componentSizeY + 20));
                     System.out.println("figure = " + f2);
//                     System.out.println("texto = " + ((LabeledDiamondFigure)f1).getText());
                     if(f2 != null) {
                         figure = new LabeledBezierConnectionFigure();
                         if(figurePosition.x < node.getPosition().x) { // a figura esta a esquerda, entao eh a parte TRUE
                             figure.setLabel("true");
                             figure.setLabelPosition(LabeledBezierConnectionFigure.Position.ESQUERDA);
                             figure.setStartConnectorPosition(Geom.west(f1.getBounds()));
                             figure.addNode(new Point2D.Double(f2.getBounds().getCenterX(),
                                                               f1.getBounds().getCenterY()));
                         } else { // a figura esta a direito, entao eh a parte FALSE
                             figure.setLabel("false");
                             figure.setStartConnectorPosition(Geom.west(f1.getBounds()));
                         }
                         figure.setEndConnectorPosition(Geom.north(f2.getBounds()));
                         try {
                             figure.draw();
                         } catch (Exception ex) {
                             Logger.getLogger(CommandsGraphFigure.class.getName()).log(Level.SEVERE, null, ex);
                         }
                     }
                }
                connectionFigures.add(figure);
            }
        }
    }

    public void fillDrawing() {
        screen = new DefaultDrawing();
        FigureGraph figureGraph = new FigureGraph(root);

        startPosition = new Point2D.Double(0, 10);

        graphToFigures(figureGraph);
        
        for(Figure figure : commandFigures) {
            screen.add(figure);
        }
        
        drawConnections(figureGraph);
        
        for(LabeledBezierConnectionFigure figure : connectionFigures) {
            screen.add(figure);
        }
    }

    public Component createPanel() {
        // Create a frame with a drawing view and a drawing editor
//        JFrame f = new JFrame("My Drawing");
//        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//        calculateHeight();
//        calculateWidth();
//        f.setSize(width, height);
//        fillDrawing();
//        DrawingView view = new DefaultDrawingView();
//        view.setDrawing(screen);
//        f.add(view.getComponent());
//        f.setVisible(true);

        fillDrawing();
        DrawingView view = new DefaultDrawingView();
        view.setDrawing(screen);
        return view.getComponent();
    }

    public int getWidth() {
        return (int) screen.getBounds().width;
    }

    public int getHeight() {
        return (int) screen.getBounds().height;
    }

    public static void main(String[] args) {
        CommandsGraphFigure commandsGraphFigure = new CommandsGraphFigure();
        try {
            commandsGraphFigure.runAnalisadores();
            commandsGraphFigure.createPanel();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CommandsGraphFigure.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CommandsGraphFigure.class.getName()).log(Level.SEVERE, null, ex);
        }


    }
}
